package cn.jnetty.remoting.tcp;
import cn.jnetty.api.annotation.JComponent;
import cn.jnetty.remoting.AbstractJnettyServer;
import cn.jnetty.remoting.code.JnettyCodecAdapterImpl;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;
/**
 * @author 猪哥亮
 * @email 1030681978@qq.com
 * @date 2020/4/2 17:06
 * 描述：
 */
@JComponent
public class JnettyTcpServer extends AbstractJnettyServer {

    public JnettyTcpServer() {
        super();
    }
    @Override
    public void init(){
        initJnettyConfig();
        port = configuration.getTcpPort();
        // TCP参数，立即发送数据，默认值为Ture（Netty默认为True而操作系统默认为False）。
        // 该值设置Nagle算法的启用，改算法将小的碎片数据连接成更大的报文来最小化所发送的报文的数量，
        // 如果需要发送一些较小的报文，则需要禁用该算法。Netty默认禁用该算法，从而最小化报文传输延时。
        bootstrap.childOption(ChannelOption.TCP_NODELAY, true);
        // Netty参数，写低水位标记，默认值32KB。当Netty的写缓冲区中的字节超过高水位之后若下降到低水位，则Channel的isWritable()返回True。
        // Netty参数，写高水位标记，默认值64KB。如果Netty的写缓冲区中的字节超过该值，Channel的isWritable()返回False。
        bootstrap.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(configuration.getDefaultLowWaterMark(),configuration.getDefaultHighWaterMark()));
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) {
                buildChannelPipeline(ch.pipeline());
            }
        });
    }
    /**
     * 构建ChannelPipeline通道.
     *
     * @param pipeline ChannelPipeline通道
     */
    protected void buildChannelPipeline(ChannelPipeline pipeline) {
        // 配置了心跳功能，则启用心跳机制.
        if (configuration.getHeartbeat() > 0) {
            pipeline.addLast("idleStateHandler", new IdleStateHandler(configuration.getHeartbeat(), 0, 0, TimeUnit.SECONDS));
        }
        if(handler == null){
            handler = new JnettyTcpHandlerImpl();
        }
        // 输出具体的Netty接受与发送封包的日志
        if (configuration.isLogActive()) {
            pipeline.addLast("logger", new LoggingHandler(LogLevel.DEBUG));
        }
        JnettyCodecAdapterImpl codecAdapter = new JnettyCodecAdapterImpl();
        // 统一默认的事件处理...
        pipeline.addLast("decoder",codecAdapter.getDecoder());
        pipeline.addLast("encoder",codecAdapter.getEncoder());
        // 初始化封包处理器.
        pipeline.addLast("handler",new JnettyTcpSimpleChannelInboundHandlerImpl(handler));
    }
}
